#include <REGX52.H>
// 十位的数字对应P0,1,2,3
// 个位的数字对应的端口号0~7
// P0_0  0
// P0_1  1
// P1_1 11

// 0 1 2 3 4 5
unsigned char key_ports[] =
    {11, 1, 5, 23, 33, 37};

// 获取数组key_ports的长度
#define KEY_COUNT (sizeof(key_ports) / sizeof(key_ports[0]))

#define GET_PORT_DATA(port_num) ((port_num == 0) ? P0 : (port_num == 1) ? P1 \
                                                    : (port_num == 2)   ? P2 \
                                                                        : P3)

// 按键配置结构体
// 数字对应端口编号的映射
typedef struct
{
    // P0,P1,P2,P3
    unsigned char port_num; // 使用哪个端口
    unsigned char mask;     // 取指定引脚的掩码
} KEY_CONFIG;

KEY_CONFIG key_configs[KEY_COUNT];

// 根据key_ports 填充key_configs，将数字转换为结构体
void init_key_config()
{
    unsigned char i;
    for (i = 0; i < KEY_COUNT; i++)
    {
        // key_ports[i] 对应一个2位十进制数
        // 取十位
        key_configs[i].port_num = key_ports[i] / 10;
        // 取个位，1左移n位，对应配置指定端口的指定引脚
        key_configs[i].mask = 1 << (key_ports[i] % 10);
    }
}

// 遍历数组对应的端口号引脚，如果值为0表示被按下，返回对应的数组下标
// 如果没有按键被按下返回0xFF
unsigned char key_scan()
{
    unsigned char i;
    for (i = 0; i < KEY_COUNT; i++)
    {
        // key_config[i].port_num 转换为P0，P1或者P2，P3
        if ((GET_PORT_DATA(key_configs[i].port_num) & key_configs[i].mask) == 0)
        {
            while ((GET_PORT_DATA(key_configs[i].port_num) & key_configs[i].mask) == 0)
            {
                /* code */
            }
            return i;
        }
    }
    return 0xFF;
}